package com.socialsoftware.ui.Contact;

import android.app.Application;
import android.util.Log;

import androidx.lifecycle.AndroidViewModel;
import androidx.lifecycle.LiveData;
import androidx.lifecycle.MediatorLiveData;
import androidx.lifecycle.MutableLiveData;
import androidx.lifecycle.Transformations;

import com.socialsoftware.model.Contact;
import com.socialsoftware.repository.ContactRepository;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class ContactsViewModel extends AndroidViewModel {

    private static final String TAG = "ContactsViewModel";
    private final ContactRepository repository;
    private final LiveData<List<Contact>> allContacts;
    private final LiveData<Boolean> isLoadingLiveData;
    private final LiveData<String> errorMessageLiveData;
    private final MutableLiveData<String> searchQueryLiveData;
    private final MediatorLiveData<List<Contact>> displayedContactsLiveData;
    
    public ContactsViewModel(Application application) {
        super(application);
        repository = new ContactRepository(application);
        allContacts = repository.getAllContacts();
        isLoadingLiveData = repository.getIsLoading();
        errorMessageLiveData = repository.getErrorMessage();
        searchQueryLiveData = new MutableLiveData<>("");
        displayedContactsLiveData = new MediatorLiveData<>();
        
        // Set up the search functionality using transformations
        LiveData<List<Contact>> searchResults = Transformations.switchMap(
                searchQueryLiveData,
                query -> {
                    if (query == null || query.isEmpty()) {
                        return allContacts;
                    } else {
                        return repository.searchContacts(query);
                    }
                }
        );
        
        // Add source to mediator live data
        displayedContactsLiveData.addSource(searchResults, contacts -> {
            displayedContactsLiveData.setValue(processContacts(contacts));
        });
        
        // Load initial data
        loadContacts();
    }
    
    public LiveData<List<Contact>> getContacts() {
        return displayedContactsLiveData;
    }
    
    public LiveData<Boolean> getIsLoading() {
        return isLoadingLiveData;
    }
    
    public LiveData<String> getErrorMessage() {
        return errorMessageLiveData;
    }
    
    /**
     * 加载联系人数据
     * 首先从本地数据库加载，然后尝试从服务器刷新
     */
    public void loadContacts() {
        Log.d(TAG, "加载联系人数据");
        
        // 首先从本地数据库加载联系人数据
        // Room的LiveData会自动通知UI更新
        
        // 然后尝试从服务器刷新数据
        // 如果有网络连接并且用户已登录，尝试从服务器获取最新数据
        repository.fetchFriendsFromServer();
    }
    
    /**
     * 强制刷新联系人数据
     * 从服务器重新获取
     */
    public void refreshContacts() {
        Log.d(TAG, "刷新联系人数据");
        repository.fetchFriendsFromServer();
    }

    
    public void searchContacts(String query) {
        Log.d(TAG, "搜索联系人: " + query);
        searchQueryLiveData.setValue(query);
    }
    
    /**
     * Star or unstar a contact
     * @param contact The contact to update
     * @param isStarred Whether the contact should be starred
     */
    public void starContact(Contact contact, boolean isStarred) {
        contact.setStarred(isStarred);
        repository.update(contact);
    }
    
    /**
     * Update a contact's information
     * @param contact The contact to update
     */
    public void updateContact(Contact contact) {
        repository.update(contact);
    }
    
    /**
     * Add a new contact
     * @param contact The contact to add
     */
    public void addContact(Contact contact) {
        repository.insert(contact);
    }
    
    /**
     * Delete a contact
     * @param contact The contact to delete
     */
    public void deleteContact(Contact contact) {
        repository.delete(contact);
    }
    
    /**
     * Process contacts to add section headers
     */
    private List<Contact> processContacts(List<Contact> rawContacts) {
        if (rawContacts == null) {
            return new ArrayList<>();
        }
        
        // Group contacts by first letter
        Map<String, List<Contact>> letterGroups = new HashMap<>();
        List<Contact> specialContacts = new ArrayList<>();
        List<Contact> starredContacts = new ArrayList<>();
        
        for (Contact contact : rawContacts) {
            if (contact.getType() == Contact.TYPE_SPECIAL) {
                specialContacts.add(contact);
            } else if (contact.isStarred()) {
                starredContacts.add(contact);
            } else {
                String firstLetter = contact.getFirstLetter();
                if (!letterGroups.containsKey(firstLetter)) {
                    letterGroups.put(firstLetter, new ArrayList<>());
                }
                letterGroups.get(firstLetter).add(contact);
            }
        }
        
        // Build final list with headers
        List<Contact> processedContacts = new ArrayList<>();
        
        // Add special contacts first (New Friends, Group Chats, etc.)
        processedContacts.addAll(specialContacts);
        
        // Add starred contacts with header
        if (!starredContacts.isEmpty()) {
            Contact starredHeader = new Contact(Contact.TYPE_HEADER, "★", null);
            processedContacts.add(starredHeader);
            processedContacts.addAll(starredContacts);
        }
        
        // Add letter groups
        List<String> letters = new ArrayList<>(letterGroups.keySet());
        Collections.sort(letters);
        
        for (String letter : letters) {
            Contact letterHeader = new Contact(Contact.TYPE_HEADER, letter, null);
            processedContacts.add(letterHeader);
            processedContacts.addAll(letterGroups.get(letter));
        }
        
        return processedContacts;
    }
}